# coding:utf-8
from odoo import models, fields, api, _
from odoo.exceptions import Warning
from datetime import datetime, timedelta


class PaulSaleOrderExtend(models.Model):
    _name = 'sale.order'
    _inherit = ["sale.order", "stock.view.quant.mixin"]

    payment_type = fields.Many2one('partner.categ', string=u'收款方式', domain="[('categ', '=', 'payment_type')]",
                                   related='partner_id.payment_type', store=True, copy=True)
    sale_order_type_id = fields.Many2one("sale.order.type", string=u"销售订单类型")
    customer_payment_term_ids = fields.Many2many('account.payment.term', related='partner_id.customer_payment_term_ids',
                                                 readonly=True)
    ol_carrier = fields.Char("Delivery Method")
    approve_reason_ids = fields.Many2many('sale.order.reason', string='Reason')
    approve_reason_count = fields.Integer(compute='_compute_approve_reason_count')
    approve_reason_str = fields.Char(compute='_compute_approve_reason_count')
    order_line_qty_sum = fields.Float(u'数量汇总', compute='_compute_qty_sum')
    state = fields.Selection([
        ('draft', 'Quotation'),
        ('sent', 'Wait Approve'),
        ('sale', 'Sales Order'),
        ('done', 'Locked'),
        ('cancel', 'Cancelled'),
    ], string='Status', readonly=True, copy=False, index=True, track_visibility='onchange', default='draft')
    product_commitment_date = fields.Datetime('Commitment Date')
    attachment_ids = fields.Many2many('ir.attachment', string=u'附件')
    ol_deposit_amount = fields.Float("Deposit Amount", compute='_compute_deposit_amount', readonly=True, store=True)
    property_product_pricelist_ids = fields.Many2many('product.pricelist',
                                                      related='partner_id.property_product_pricelist_ids',
                                                      readonly=True)
    partner_address = fields.Char(' ')
    partner_invoice_address = fields.Char(' ')
    partner_shipping_address = fields.Char(' ')
    reject_approve = fields.Boolean('Reject Approve Status', default=False)
    source_order_id = fields.Many2one("sale.order", string=u"Source Order",
                                      readonly=True, copy=False)

    begin_order_id = fields.Many2one("sale.order", string=u"Begin Order",
                                     copy=True, domain="[('partner_id','=',partner_id)]")
    begin_order_count = fields.Integer(compute='_compute_begin_order', string='Receptions', default=0)
    begin_order_ids = fields.Many2many('sale.order', compute='_compute_begin_order', string='Receptions', copy=False, store=False)
    return_picking = fields.Many2one('stock.picking', string=u"退货单",
                                     domain="[('partner_id','=',partner_shipping_id),('picking_type_id.name','ilike',u'销售退货')]")
    is_copy = fields.Boolean('Is Copy', default=False, copy=False)
    order_line_clone = fields.One2many('sale.order.line.clone', 'order_id', string='Order Lines',
                                       states={'cancel': [('readonly', True)], 'done': [('readonly', True)]})
    notifying_party = fields.Char('Receiver Notifying Party')
    freight_forwarder = fields.Char('Freight Forwarder')
    payer = fields.Many2one('res.partner', string='Payer')
    receiver = fields.Many2one('res.partner', string='Receiver')
    attention = fields.Text('Matters needing attention')
    packing_claim = fields.Many2one('partner.categ', string='Packing Claim',
                                    domain="[('categ', '=', 'packing_claim')]",
                                    related="partner_id.packing_claim")
    country_group_id = fields.Many2one("res.country.group", string="Delivery Area")
    country_id = fields.Many2one("res.country", string=u'出货国家', readonly=True)
    last_picking_date = fields.Date(compute='_compute_last_picking_date', string=u'实际日期',
                                    help=u"系统计算出SO最早的出货日")
    product_uom_ids = fields.One2many('product.uom', compute='_calc_order_uom_ids', store=False)


    currency_id = fields.Many2one("res.currency",string="Currency",
                               related='pricelist_id.currency_id',store=True,required=True)
    def _calc_order_uom_ids(self):
        for order in self:
            order.product_uom_ids = order.order_line.mapped('product_uom')

    # @api.onchange(order_line_clone)
    # def sync_price_unit(self):
    #     self.order_line = self.order_line_clone

    @api.depends('order_line.product_uom_qty')
    def _compute_qty_sum(self):
        for order in self:
            order.update({
                'order_line_qty_sum': sum(order.mapped('order_line.product_uom_qty'))
            })

    @api.depends('order_line.price_total', 'order_line_clone.price_total')
    def _amount_all(self):
        for order in self:

            if order.is_copy is True:
                for line_c in order.order_line_clone:
                    for line in order.order_line:
                        if line.origin_id == line_c.origin_id:
                            line.price_unit = line_c.price_unit
                            line._compute_amount()
            """
            Compute the total amounts of the SO.
            """
            amount_untaxed = amount_tax = 0.0
            for line in order.order_line:
                amount_untaxed += line.price_subtotal
                # FORWARDPORT UP TO 10.0
                if order.company_id.tax_calculation_rounding_method == 'round_globally':
                    price = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
                    taxes = line.tax_id.compute_all(price, line.order_id.currency_id, line.product_uom_qty, product=line.product_id, partner=order.partner_shipping_id)
                    amount_tax += sum(t.get('amount', 0.0) for t in taxes.get('taxes', []))
                else:
                    amount_tax += line.price_tax
            order.update({
                'amount_untaxed': order.pricelist_id.currency_id.round(amount_untaxed),
                'amount_tax': order.pricelist_id.currency_id.round(amount_tax),
                'amount_total': amount_untaxed + amount_tax,
            })

    @api.multi
    def change_and_copy(self):
        self.ensure_one()
        if self.is_copy:
            raise Warning(u'此单已经为复制订单,请使用原始订单进行复制')
        for sl in self.order_line:
            sl.origin_id = sl.id
        new_order = self.copy()
        new_order.requested_date = self.requested_date
        new_order.source_order_id = self
        new_order.order_line_clone = [(5, 0)]
        for line in self.order_line:
            tax = None
            if len(line.tax_id) > 0:
                tax = line.tax_id[0]
            new_order.order_line_clone = [(0, 0, {
                'origin_id': line.id,
                'currency_id': line.currency_id,
                'customer_lead': line.customer_lead,
                'customer_order': line.customer_order,
                # 'date_order': line.date_order,
                # 'datetime_order': line.datetime_order,
                'discount': line.discount,
                # 'incoterm': line.incoterm,
                'length_weight': line.length_weight,
                'lot': line.lot,
                # 'margin': line.margin,
                'name': line.name,
                'note': line.note,
                'order_id': line.order_id,
                'order_partner_id': line.order_partner_id,
                'price_reduce': line.price_reduce,
                'price_reduce_taxexcl': line.price_reduce_taxexcl,
                'price_reduce_taxinc': line.price_reduce_taxinc,
                'price_subtotal': line.price_subtotal,
                'price_tax': line.price_tax,
                'price_total': line.price_total,
                'price_unit': line.price_unit,
                'product_id': line.product_id,
                'product_packaging': line.product_packaging,
                'product_tmpl_id': line.product_tmpl_id,
                'product_uom': line.product_uom,
                'product_uom_qty': line.product_uom_qty,
                # 'purchase_price': line.purchase_price,
                # 'route_id': line.route_id,
                # 'salesman_id': line.salesman_id,
                'sequence': line.sequence,
                'tax_id': tax,
                'state': 'draft',
                'technological_requirements': line.technological_requirements
            })]
        new_order.is_copy = True
        new_order.client_order_ref = self.client_order_ref
        # new_order.approve_reason_ids = [(5, 0)]
        if self.state in ['draft', 'sent', 'sale']:
            self.write({'state': 'cancel'})
        if len(self.approve_reason_ids) > 1:
            try:
                new_order.action_confirm()
            except:
                new_order.action_confirm_with_credit()
        return new_order

    def _compute_begin_order(self):
        for so in self:
            begin_order_ids = self.env['sale.order'].search([('begin_order_id', '=', so.begin_order_id.id)])
            so.begin_order_ids = begin_order_ids
            so.begin_order_count = len(begin_order_ids)

    @api.multi
    def action_view_begin_order(self):
        self.ensure_one()
        action = self.env.ref('sale.action_orders').read()[0]
        if self.begin_order_id.id:
            action['domain'] = [('begin_order_id', 'in', self.begin_order_ids.ids)]
        return action


    @api.multi
    def action_clean_approve_reason(self):
        self.ensure_one()
        self.write({'approve_reason_ids': [(5, 0)]})

    @api.onchange('partner_id', 'partner_shipping_id')
    def _onchange_partner_id(self):
        if self.partner_id:
            self.partner_address = self.partner_id._display_address(without_company=True)
        else:
            self.partner_address = False
        if self.partner_shipping_id:
            self.country_id = self.partner_shipping_id.country_id

        return {
            'domain': {'pricelist_id': [('id', 'in', self.property_product_pricelist_ids.ids)], 'payment_term_id': [('id', 'in', self.customer_payment_term_ids.ids)]},
        }


    @api.onchange('pricelist_id', 'payment_term_id')
    def _onchange_pricelist_id(self):
        if self.pricelist_id.id not in self.property_product_pricelist_ids.ids:
            self.pricelist_id = self.property_product_pricelist_ids and self.property_product_pricelist_ids[0] or False
        if self.payment_term_id.id not in self.customer_payment_term_ids.ids:
            self.payment_term_id = self.customer_payment_term_ids and self.customer_payment_term_ids[0] or False
        return {
            'domain': {'pricelist_id': [('id', 'in', self.property_product_pricelist_ids.ids)],
                       'payment_term_id': [('id', 'in', self.customer_payment_term_ids.ids)]},
        }

    @api.onchange('partner_invoice_id', 'partner_shipping_id')
    def _onchange_invoice_and_shipping_partner_id(self):
        if self.partner_shipping_id:
            self.partner_shipping_address = self.partner_shipping_id._display_address(without_company=True)
        else:
            self.partner_shipping_address = False

        if self.partner_invoice_id:
            self.partner_invoice_address = self.partner_invoice_id._display_address(without_company=True)
        else:
            self.partner_invoice_address = False

    @api.depends('approve_reason_ids')
    def _compute_approve_reason_count(self):
        for order in self:
            order.approve_reason_count = len(order.approve_reason_ids)
            arr = []
            for reason in order.approve_reason_ids:
                arr.append(reason.name)
            if len(arr) > 0:
                order.approve_reason_str = ','.join(arr)

    @api.multi
    def action_quotation_send(self):
        self.ensure_one()
        ir_model_data = self.env['ir.model.data']
        try:
            compose_form_id = ir_model_data.get_object_reference('sales_order_extend', 'sale_order_reason_wizard')[1]
        except ValueError:
            compose_form_id = False
        ctx = dict()
        ctx.update({
            'default_model': 'sale.order',
            'sale_order_ids': self.ids[0],
            'mark_so_as_sent': True
        })
        return {
            'type': 'ir.actions.act_window',
            'view_type': 'form',
            'view_mode': 'form',
            'res_model': 'sale.order.reason.wizard',
            'views': [(compose_form_id, 'form')],
            'view_id': compose_form_id,
            'target': 'new',
            'context': ctx,
        }

    @api.multi
    def action_cancel(self):
        self.write({'procurement_group_id': False, 'reject_approve': False})
        return super(PaulSaleOrderExtend, self).action_cancel()

    @api.multi
    def action_reject_approve(self):
        self.write({'state': 'cancel', 'reject_approve': True})

    @api.multi
    def action_view_quants(self):
        self.ensure_one()
        products = self.order_line.mapped("product_id")
        return self.action_view_quant_by_product_ids(products.ids)

    @api.depends('order_line.qty_invoiced')
    def _compute_deposit_amount(self):
        deposit_product_id = self.env['ir.values'].get_default('sale.config.settings', 'deposit_product_id_setting')
        for order in self:
            deposit_amount = 0
            for line in order.order_line:
                if line.product_id.id == deposit_product_id:
                    deposit_amount += line.price_unit * line.qty_invoiced
            order.ol_deposit_amount = deposit_amount

    @api.multi
    def write(self, vals):
        if self.is_copy is True:
            for line_c in self.order_line_clone:
                for line in self.order_line:
                    if line.id == line_c.origin_id:
                        line.price_unit = line_c.price_unit
        if vals.get('partner_id', False):
            vals['partner_address'] = self.env['res.partner'].search([('id', '=', vals['partner_id'])])._display_address(without_company=True)
        if vals.get('partner_shipping_id', False):
            vals['partner_shipping_address'] = self.env['res.partner'].search([('id', '=', vals['partner_shipping_id'])])._display_address(without_company=True)
        if vals.get('partner_invoice_id', False):
            vals['partner_invoice_address'] = self.env['res.partner'].search([('id', '=', vals['partner_invoice_id'])])._display_address(without_company=True)
        if self.requested_date or vals.get('requested_date') is not None:
            if self.is_copy is False:
                requested_date = self.requested_date
                if vals.get('requested_date'):
                    requested_date = vals.get('requested_date')
                if self.state in ('sent', 'draft') and requested_date < (fields.Date.today()+' 00:00:00'):
                    raise Warning(_("The date requested by the customer is "
                                    "sooner than the current date. You may be "
                                    "unable to honor the customer's request."))
        if vals.get('begin_order_id') is not None and not vals.get('begin_order_id'):
            vals['begin_order_id'] = self.id
        return super(PaulSaleOrderExtend, self).write(vals)

    @api.model
    def create(self, vals):
        vals['partner_address'] = self.env['res.partner'].search([('id', '=', vals['partner_id'])])._display_address(without_company=True)
        vals['partner_shipping_address'] = self.env['res.partner'].search([('id', '=', vals['partner_shipping_id'])])._display_address(without_company=True)
        vals['partner_invoice_address'] = self.env['res.partner'].search([('id', '=', vals['partner_invoice_id'])])._display_address(without_company=True)
        res = super(PaulSaleOrderExtend, self).create(vals)
        if not vals.get('begin_order_id', False):
            res.begin_order_id = res.id
        return res

    @api.multi
    def action_confirm(self):
        self.ensure_one()
        deposit_product_id = self.env['ir.values'].get_default('sale.config.settings', 'deposit_product_id_setting')
        issue_line = self.order_line.filtered(lambda l: l.price_unit == 0 and l.product_id.id != deposit_product_id)
        if len(issue_line) > 0 and len(self.approve_reason_ids) == 0:
            raise Warning(_('Approve reasons is required.'))
        return super(PaulSaleOrderExtend, self).action_confirm()

    def _compute_last_picking_date(self):
        super(PaulSaleOrderExtend, self)._compute_picking_ids()
        for order in self:
            dates_list = []
            for pick in order.picking_ids:
                if fields.Datetime.from_string(pick.date_done):
                    dates_list.append(fields.Datetime.from_string(pick.date_done))
            if dates_list and min(dates_list) is not None:
                order.update({'last_picking_date': fields.Datetime.to_string(min(dates_list) + timedelta(hours=8))})



